package io.github.echarts.model.context;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 配置上下文
 * <p>
 * 存储图表配置过程中的上下文信息，如数据统计、图表类型推断结果等。
 * 作为配置处理各阶段之间的数据传递媒介。
 * </p>
 */
public class ConfigurationContext {
    
    /**
     * 数据统计信息
     */
    private DataStatistics dataStatistics = new DataStatistics();
    
    /**
     * 附加信息
     */
    private final Map<String, Object> additionalInfo = new HashMap<>();
    
    /**
     * 图表类型
     */
    private ChartType chartType;
    
    /**
     * 图表宽度
     */
    private final int width;
    
    /**
     * 图表高度
     */
    private final int height;
    
    /**
     * 构造函数
     * 
     * @param width 图表宽度
     * @param height 图表高度
     */
    public ConfigurationContext(int width, int height) {
        this.width = width;
        this.height = height;
        
        // 将宽高信息添加到附加信息中
        additionalInfo.put("width", width);
        additionalInfo.put("height", height);
    }
    
    /**
     * 获取数据统计信息
     * 
     * @return 数据统计信息
     */
    public DataStatistics getDataStatistics() {
        return dataStatistics;
    }
    
    /**
     * 设置数据统计信息
     * 
     * @param dataStatistics 数据统计信息
     */
    public void setDataStatistics(DataStatistics dataStatistics) {
        this.dataStatistics = dataStatistics;
    }
    
    /**
     * 获取图表类型
     * 
     * @return 图表类型
     */
    public ChartType getChartType() {
        return chartType;
    }
    
    /**
     * 设置图表类型
     * 
     * @param chartType 图表类型
     */
    public void setChartType(ChartType chartType) {
        this.chartType = chartType;
        
        // 同时更新附加信息
        if (chartType != null) {
            additionalInfo.put("chartType", chartType.toString());
        }
    }
    
    /**
     * 获取图表宽度
     * 
     * @return 图表宽度
     */
    public int getWidth() {
        return width;
    }
    
    /**
     * 获取图表高度
     * 
     * @return 图表高度
     */
    public int getHeight() {
        return height;
    }
    
    /**
     * 获取指定键的值
     * 
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return additionalInfo.get(key);
    }
    
    /**
     * 设置指定键的值
     * 
     * @param key 键
     * @param value 值
     */
    public void put(String key, Object value) {
        additionalInfo.put(key, value);
    }
    
    /**
     * 设置指定键的布尔值
     * 
     * @param key 键
     * @param value 布尔值
     */
    public void put(String key, boolean value) {
        additionalInfo.put(key, Boolean.valueOf(value));
    }
    
    /**
     * 设置指定键的整数值
     * 
     * @param key 键
     * @param value 整数值
     */
    public void put(String key, int value) {
        additionalInfo.put(key, value);
    }
    
    // 为解决编译错误增加的方法 - addInfo系列作为put的别名
    
    /**
     * 添加信息(字符串)
     * @param key 键
     * @param value 字符串值
     */
    public void addInfo(String key, String value) {
        put(key, value);
    }
    
    /**
     * 添加信息(布尔值)
     * @param key 键
     * @param value 布尔值
     */
    public void addInfo(String key, boolean value) {
        put(key, value);
    }
    
    /**
     * 添加信息(整数)
     * @param key 键
     * @param value 整数值
     */
    public void addInfo(String key, int value) {
        put(key, value);
    }
    
    /**
     * 添加信息(双精度浮点数)
     * @param key 键
     * @param value 双精度浮点数值
     */
    public void addInfo(String key, double value) {
        put(key, value);
    }
    
    /**
     * 添加信息(Boolean对象)
     * @param key 键
     * @param value Boolean对象
     */
    public void addInfo(String key, Boolean value) {
        put(key, value);
    }
    
    /**
     * 添加信息(字符串列表)
     * @param key 键
     * @param value 字符串列表
     */
    public void addInfo(String key, List<String> value) {
        put(key, value);
    }
    
    /**
     * 添加信息(字符串数组)
     * @param key 键
     * @param value 字符串数组
     */
    public void addInfo(String key, String[] value) {
        put(key, value);
    }
    
    /**
     * 添加信息(任何映射)
     * @param key 键
     * @param value 映射
     */
    public void addInfo(String key, Map<?, ?> value) {
        put(key, value);
    }
    
    // getInfo作为get的别名
    
    /**
     * 获取信息
     * @param key 键
     * @return 值
     */
    public Object getInfo(String key) {
        return get(key);
    }
    
    /**
     * 数据统计信息类
     */
    public class DataStatistics {
        private final Map<String, Object> statistics = new HashMap<>();
        
        // 添加基本的统计指标
        private double min = Double.MAX_VALUE;
        private double max = Double.MIN_VALUE;
        private double sum = 0;
        private double average = 0;
        private double median = 0;
        private int dataPointCount = 0;
        private int categoryCount = 0;
        private boolean hasNegativeValues = false;
        private boolean hasSingleValue = true; // 默认为true，直到发现第二个不同值
        private Double firstValue = null;
        
        /**
         * 设置统计值
         * 
         * @param key 键
         * @param value 值
         */
        public void set(String key, Object value) {
            statistics.put(key, value);
        }
        
        /**
         * 获取统计值
         * 
         * @param key 键
         * @return 值
         */
        public Object get(String key) {
            return statistics.get(key);
        }
        
        /**
         * 检查是否包含某个键
         * 
         * @param key 键
         * @return 是否包含
         */
        public boolean containsKey(String key) {
            return statistics.containsKey(key);
        }
        
        /**
         * 获取是否为分类数据
         * 
         * @return 是否为分类数据
         */
        public Boolean getIsCategoryData() {
            Object value = statistics.get("isCategoryData");
            return value instanceof Boolean ? (Boolean) value : null;
        }
        
        /**
         * 设置是否为分类数据
         * 
         * @param isCategoryData 是否为分类数据
         */
        public void setIsCategoryData(Boolean isCategoryData) {
            statistics.put("isCategoryData", isCategoryData);
        }
        
        /**
         * 获取是否为时间数据
         * 
         * @return 是否为时间数据
         */
        public Boolean getIsTimeData() {
            Object value = statistics.get("isTimeData");
            return value instanceof Boolean ? (Boolean) value : null;
        }
        
        /**
         * 设置是否为时间数据
         * 
         * @param isTimeData 是否为时间数据
         */
        public void setIsTimeData(Boolean isTimeData) {
            statistics.put("isTimeData", isTimeData);
        }
        
        /**
         * 获取是否有负值
         * 
         * @return 是否有负值
         */
        public Boolean getHasNegativeValues() {
            Object value = statistics.get("hasNegativeValues");
            return value instanceof Boolean ? (Boolean) value : Boolean.FALSE;
        }
        
        /**
         * 设置是否有负值
         * 
         * @param hasNegativeValues 是否有负值
         */
        public void setHasNegativeValues(Boolean hasNegativeValues) {
            statistics.put("hasNegativeValues", hasNegativeValues);
            this.hasNegativeValues = Boolean.TRUE.equals(hasNegativeValues);
        }
        
        /**
         * 清除所有统计数据
         */
        public void clear() {
            statistics.clear();
            reset();
        }
        
        // 为解决编译错误添加的方法
        
        /**
         * 重置统计数据
         */
        public void reset() {
            min = Double.MAX_VALUE;
            max = Double.MIN_VALUE;
            sum = 0;
            average = 0;
            median = 0;
            dataPointCount = 0;
            categoryCount = 0;
            hasNegativeValues = false;
            hasSingleValue = true;
            firstValue = null;
        }
        
        /**
         * 使用新值更新统计数据
         * @param value 数值
         */
        public void updateWithValue(double value) {
            // 更新最小值和最大值
            if (value < min) min = value;
            if (value > max) max = value;
            
            // 更新总和和计数
            sum += value;
            dataPointCount++;
            
            // 计算平均值
            average = sum / dataPointCount;
            
            // 检查是否有负值
            if (value < 0) {
                hasNegativeValues = true;
                setHasNegativeValues(true);
            }
            
            // 检查是否只有单一值
            if (firstValue == null) {
                firstValue = value;
            } else if (hasSingleValue && Math.abs(firstValue - value) > 0.00001) {
                hasSingleValue = false;
            }
        }
        
        /**
         * 增加分类计数
         */
        public void incrementCategoryCount() {
            categoryCount++;
        }
        
        /**
         * 获取最小值
         * @return 最小值
         */
        public double getMin() {
            return min;
        }
        
        /**
         * 获取最大值
         * @return 最大值
         */
        public double getMax() {
            return max;
        }
        
        /**
         * 获取平均值
         * @return 平均值
         */
        public double getAverage() {
            return average;
        }
        
        /**
         * 获取中位数
         * @return 中位数
         */
        public double getMedian() {
            return median;
        }
        
        /**
         * 设置中位数
         * @param median 中位数
         */
        public void setMedian(double median) {
            this.median = median;
        }
        
        /**
         * 获取数据点数量
         * @return 数据点数量
         */
        public int getDataPointCount() {
            return dataPointCount;
        }
        
        /**
         * 获取分类数量
         * @return 分类数量
         */
        public int getCategoryCount() {
            return categoryCount;
        }
        
        /**
         * 是否有负值
         * @return 是否有负值
         */
        public boolean isHasNegativeValues() {
            return hasNegativeValues;
        }
        
        /**
         * 是否只有单一值
         * @return 是否只有单一值
         */
        public boolean isHasSingleValue() {
            return hasSingleValue;
        }
        
        /**
         * 存储布尔类型的键值对
         * 
         * @param key 键
         * @param value 值
         */
        public void put(String key, boolean value) {
            additionalInfo.put(key, Boolean.valueOf(value));
        }
    }
} 